//
//  Basic.swift
//  ShareCar
//
//  Created by lishuai on 2018/6/21.
//  Copyright © 2018年 changqingkeji. All rights reserved.
//

import Foundation
import CryptoSwift

struct Message {
    let code: Int
    let msg: String
}

struct Base<T>: Codable where T: Codable {
    let code: Int
    let msg: String
    let time: String
    let data: T?
    
    private static func sign(_ parameters: [String: Any]?) -> [String: Any] {
        var params: [String: Any] = ["time": Date().milliStamp]
        
        if let p = parameters {
            for (k, v) in p {
                if v is Double || v is Float {
                    params[k] = "\(v)"
                } else if v is String {
                    let t = v as! String
                    params[k] = t.trimmingCharacters(in: .whitespaces)
                } else {
                    params[k] = v
                }
            }
        }
        
        var signString = ""
        let keys = params.keys.sorted(by: < )
        
        for k in keys {
            if !(params[k] is Array<Any>) && !(params[k] is [AnyHashable:AnyHashable] ) {
                signString.append(k)
                signString.append("\(params[k] ?? "")")
            }
        }
        
        signString.append(kApiPrivateKey)
        params["signature"] = signString.lowercased().md5()
        
        return params
    }
    
    static func request(URIString: String,
                        parameters: [String: Any]? = nil,
                        success: @escaping (T?) -> (),
                        failure: @escaping (Message, T?) -> ()) {
        
        let parms = URIString == "user/get_verification_code" ? parameters : sign(parameters)
        
        HTTPRequest.request(URIString, parameters: parms, success: { data in
            do {
                let rs = try JSONDecoder().decode(Base<T>.self, from: data as! Data)
                if rs.code != 1 {
                    failure(Message(code: rs.code, msg: rs.msg), rs.data)
                } else {
                    success(rs.data)
                }
            } catch (let error) {
                #if DEBUG
                let jsonString = String(data: data as! Data, encoding: String.Encoding.utf8)
                print("++++++++++++++++++++++++++++++++")
                print("uri:", URIString)
                print("parameters:", parameters ?? [])
                print("json:", jsonString ?? "")
                print("json解析错误:", error)
                print("++++++++++++++++++++++++++++++++")
                failure(Message(code: 0, msg: "JSON解析错误:\(jsonString ?? "")"), nil)
                #else
                failure(Message(code: Int.min, msg: "抱歉，服务暂时异常，请稍后重试，谢谢。（1050）"), nil)
                #endif
            }
        }) { error in
            failure(Message(code: 0, msg: "网络请求错误"), nil)
        }
    }
    
    static func upload(URIString: String,
                       files: [HTTPRequest.File],
                       parameters: [String: Any]? = nil,
                       success: @escaping (T?) -> (),
                       failure: @escaping (Message, T?) -> ()) {
        
        let parms = URIString == "user/get_verification_code" ? parameters : sign(parameters)
        
        HTTPRequest.upload(URIString, files: files, parameters: parms, success: { data in
            do {
                let rs = try JSONDecoder().decode(Base<T>.self, from: data as! Data)
                if rs.code != 1 {
                    failure(Message(code: rs.code, msg: rs.msg), rs.data)
                } else {
                    success(rs.data)
                }
            } catch {
                failure(Message(code: Int.min, msg: "抱歉，服务暂时异常，请稍后重试，谢谢。（1050）"), nil)
            }
        }) { error in
            failure(Message(code: 0, msg: "网络请求错误"), nil)
        }
    }
}
